package Test09;

//反射

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;

/*
Class类中用于获取成员方法的方法
    Method[] getMethods():返回==所有公共==成员方法对象的数组，包括继承的
    Method[] getDeclaredMethods():返回==所有==成员方法对象的数组，不包括继承的
    Method getMethod(String name, Class<?>... parameterTypes):返回==单个公共==成员方法对象
    Method getDeclaredMethod(String name, Class<?>... parameterTypes):返回==单个==成员方法对象、

Method类中用于创建对象的方法
    Object invoke(Object obj, Object... args):运行方法
    参数一:用obj对象调用该方法
    参数二:调用方法的传递的参数(如果没有就不写)
    返回值:方法的返回值(如果没有就不写)

    获取方法的修饰符
    获取方法的名字
    获取方法的形参
    获取方法的返回值
    获取方法的抛出的异常
 */
public class Test04 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {

        //1、获取class字节码文件对象
        Class clazz = Class.forName("Test09.Student04");

        /*//2、获取里面所有的公共的方法（包含父类中所有的公共方法）
        Method[] methods = clazz.getMethods();
        for (Method method : methods) {
            System.out.println(method);
        }*/

        /*//3、获取里面所有的的方法（不能获取父类的，但是可以获取本类中私有的方法）
        Method[] methods = clazz.getDeclaredMethods();
        for (Method method : methods) {
            System.out.println(method);
        }*/

        //4、获取指定的单一方法
        Method m = clazz.getDeclaredMethod("eat", String.class);
        System.out.println(m);

        //获取方法的修饰符
        int modifiers = m.getModifiers();
        System.out.println(modifiers);

        //获取方法的名字
        String name = m.getName();
        System.out.println(name);

        //获取方法的形参
        Parameter[] parameters = m.getParameters();
        for (Parameter parameter : parameters) {
            System.out.println(parameter);
        }

        //获取方法抛出的异常
        Class[] exceptionTypes = m.getExceptionTypes();
        for (Class exceptionType : exceptionTypes) {
            System.out.println(exceptionType);
        }

        //方法运行
        /*Method类中用于创建对象的方法
        Object invoke(Object obj, Object... args):运行方法
        参数一:用obj对象调用该方法
        参数二:调用方法的传递的参数(如果没有就不写)
        返回值:方法的返回值(如果没有就不写)*/

        Student04 stu = new Student04();
        m.setAccessible(true);
        //参数一stu:表示方法的调用者
        //参数二"汉堡包":表示在调用方法的时候传递的实际参数
        String result = (String) m.invoke(stu, "汉堡包");
        System.out.println(result);
    }
}

class Student04 {

    private String name;
    private int age;

    public Student04() {
    }

    public Student04(String name, int age) {
        this.name = name;
        this.age = age;
    }

    /**
     * 获取
     *
     * @return name
     */
    public String getName() {
        return name;
    }

    /**
     * 设置
     *
     * @param name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * 获取
     *
     * @return age
     */
    public int getAge() {
        return age;
    }

    /**
     * 设置
     *
     * @param age
     */
    public void setAge(int age) {
        this.age = age;
    }

    public void sleep() {
        System.out.println("睡觉");
    }

    private String eat(String something) throws IOException, NullPointerException, ClassCastException {
        System.out.println("在吃" + something);
        return "奥里给";
    }

    private void eat(String something, int a) {
        System.out.println("在吃" + something);
    }

    public String toString() {
        return "Student04{name = " + name + ", age = " + age + "}";
    }
}
